package org.study.redis.api.util.jedis;

import org.study.redis.api.constant.RedisProperties;
import redis.clients.jedis.*;

import java.time.Duration;

/**
 * 自定义基于 Jedis 的 Redis 连接池。
 * 可以在 {@link org.apache.commons.pool2.impl.BaseObjectPoolConfig} 中查看全部参数的默认值
 *
 * @author doveylovey
 * @email 1135782208@qq.com
 * @date 2022年04月23日
 */
public class SysJedisPool {
    private static JedisPool pool = null;

    static {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        // 资源池中的最大连接数，默认值为8
        poolConfig.setMaxTotal(8);
        // 资源池允许的最大空闲连接数，默认值为8
        poolConfig.setMaxIdle(8);
        // 资源池确保的最少空闲连接数，默认值为0
        poolConfig.setMinIdle(0);
        // 当资源池用尽后，调用者是否要等待，默认值为true。只有当值为 true 时下面的 setMaxWait 才会生效，建议使用默认值
        poolConfig.setBlockWhenExhausted(true);
        // 当资源池连接用尽后，调用者的最大等待时间，默认值为-1，表示永不超时，不建议使用默认值
        poolConfig.setMaxWait(Duration.ofSeconds(30L));
        // 向资源池借用连接时是否做连接有效性检测，检测到的无效连接将会被移除，默认值为false，业务量很大时候建议设置为false，减少一次ping的开销
        poolConfig.setTestOnBorrow(false);
        // 向资源池归还连接时是否做连接有效性检测，检测到无效连接将会被移除，默认值为false，业务量很大时候建议设置为false，减少一次ping的开销
        poolConfig.setTestOnReturn(true);
        // 是否开启JMX监控，默认值为true，建议开启，请注意应用本身也需要开启
        poolConfig.setJmxEnabled(true);
        // 空闲Jedis对象检测由下列四个参数组合完成，testWhileIdle是该功能的开关
        // 是否开启空闲资源检测，默认值为false，建议设置为true
        poolConfig.setTestWhileIdle(true);
        // 空闲资源的检测周期，默认值为-1，表示不检测，建议设置
        poolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(10L));
        // 资源池中资源的最小空闲时间，达到此值后空闲资源将被移除，默认值为30分钟，可根据自身业务决定，一般默认值即可
        poolConfig.setMinEvictableIdleDuration(Duration.ofMinutes(30L));
        // 做空闲资源检测时，每次检测资源的个数，默认值为3，可根据自身应用连接数进行微调，如果设置为 -1，表示对所有连接做空闲监测
        poolConfig.setNumTestsPerEvictionRun(3);
        pool = new JedisPool(poolConfig, RedisProperties.HOST, RedisProperties.PORT, RedisProperties.CONNECTION_TIMEOUT, RedisProperties.PASSWORD);
    }

    private SysJedisPool() {
        throw new AssertionError("不能实例化工具类");
    }

    public static Jedis getResource() {
        return pool.getResource();
    }

    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
}
